package org.abacus.dbtojava;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public abstract class FileService {
	protected static final Random RANDOM = new Random();
	protected static final ContentBuilderTools contentBuilderTools = ContentBuilderTools.getInstance();

	public static enum FileType {
		MODEL, DAO, DAOIMPL, SERVICE, SERVICEIMPL, ACTION, HBMXML;
	}

	DBService dbService = new DBService();
	private List<String> tables;

	private Map<String, List<Column>> columnsMap = new HashMap<String, List<Column>>();

	public FileService() {
		super();
		tables = dbService.getTables();
	}

	public void createModelFile() {
		String path = this.getPath(FileType.MODEL);
		for (String table : tables) {
			String content = this.getModeContent(table, this.getColumns(table));
			this.createFile(FileType.MODEL, path, table, content);
		}
	}

	public void createHbmXmlFile() {
		String path = this.getPath(FileType.HBMXML);
		for (String table : tables) {
			String content = this.getHbmXmlContent(table, this.getColumns(table));
			this.createFile(FileType.HBMXML, path, table, content);
		}
	}

	protected void createFile(FileType model, String path, String table, String content) {
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
		file = new File(path, this.getFileName(model, table));
		FileOutputStream fos = null;
		OutputStreamWriter osw = null;
		BufferedWriter bw = null;
		try {
			fos = new FileOutputStream(file);
			osw = new OutputStreamWriter(fos, Config.FILE_ENCODING);
			bw = new BufferedWriter(osw);
			bw.write(content);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (null != bw) {
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != osw) {
				try {
					osw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != fos) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private List<Column> getColumns(String tableNamePattern) {
		List<Column> columns = columnsMap.get(tableNamePattern);
		if (null == columns) {
			columns = dbService.getColumns(tableNamePattern);
			columnsMap.put(tableNamePattern, columns);
		}
		return columns;
	}

	public void createDaoFile() {
		String path = this.getPath(FileType.DAO);
		for (String table : tables) {
			String content = this.getDaoContent(table);
			this.createFile(FileType.DAO, path, table, content);
		}
	}

	public void createDaoImplFile() {
		String path = this.getPath(FileType.DAOIMPL);
		for (String table : tables) {
			String content = this.getDaoImplContent(table);
			this.createFile(FileType.DAOIMPL, path, table, content);
		}
	}

	public void createServiceFile() {
		String path = this.getPath(FileType.SERVICE);
		for (String table : tables) {
			String content = this.getServiceContent(table);
			this.createFile(FileType.SERVICE, path, table, content);
		}
	}

	public void createServiceImplFile() {
		String path = this.getPath(FileType.SERVICEIMPL);
		for (String table : tables) {
			String content = this.getServiceImplContent(table);
			this.createFile(FileType.SERVICEIMPL, path, table, content);
		}
	}

	public void createActionFile() {
		String path = this.getPath(FileType.ACTION);
		for (String table : tables) {
			String content = this.getActionContent(table);
			this.createFile(FileType.ACTION, path, table, content);
		}
	}

	protected String getSerialVersionUID() {
		return contentBuilderTools.getSerialVersionUID();
	}

	protected String firstToUpperCase(String s) {
		if (null == s) {
			return null;
		}
		return contentBuilderTools.firstToUpperCase(s);
	}

	protected String firstToLowerCase(String s) {
		if (null == s) {
			return null;
		}
		return contentBuilderTools.firstToLowerCase(s);
	}

	protected String getClassName(String s) {
		if (null == s) {
			return null;
		}
		return contentBuilderTools.getClassName(s);
	}

	protected String getAttributeName(String s) {
		if (null == s) {
			return null;
		}
		return contentBuilderTools.getAttributeName(s);
	}

	protected String getAttributeContent(String columnType, String attributeName) {
		return contentBuilderTools.getAttributeContent(columnType, attributeName);
	}

	protected String getGetterContent(String columnType, String attributeName) {
		return contentBuilderTools.getGetterContent(columnType, attributeName);
	}

	protected String getSetterContent(String columnType, String attributeName) {
		return contentBuilderTools.getSetterContent(columnType, attributeName);
	}

	protected void modelAttributeContent(StringBuilder sb, StringBuilder getterAndSetter, String columnType, String attributeName) {
		// attribute
		sb.append(getAttributeContent(columnType, attributeName));
		// getter
		getterAndSetter.append(getGetterContent(columnType, attributeName));
		// setter
		getterAndSetter.append(getSetterContent(columnType, attributeName));
	}

	abstract String getPath(FileType fileType);

	abstract String getModeContent(String table, List<Column> columns);

	abstract String getHbmXmlContent(String table, List<Column> columns);

	abstract String getDaoContent(String table);

	abstract String getDaoImplContent(String table);

	abstract String getServiceContent(String table);

	abstract String getServiceImplContent(String table);

	abstract String getActionContent(String table);

	abstract String getPackage(FileType fileType);

	abstract String getFileName(FileType fileType, String table);
}
